#include <iostream>
#include <cstdio>
#include <fstream>

extern "C" {
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
}

int main() {
    av_register_all();//ffmpeg 3.x version
    avdevice_register_all();
    AVFormatContext *fmt_ctx = nullptr;
    AVInputFormat *input_fmt = av_find_input_format("pulse"); // 音频设备的输入格式，如alsa、pulse等
    const char *dev_name = "default"; // microphone device name
    AVDictionary *format_opts = nullptr;//set stream format options
    av_dict_set(&format_opts, "sample_rate", "16000", 0);//set audio sample
    av_dict_set(&format_opts, "channels", "1", 0);//set audio channel
    av_dict_set(&format_opts, "fragment_size", "25600", 0);//set audio fragment size
    // open audio device
    if (avformat_open_input(&fmt_ctx, dev_name, input_fmt, &format_opts) != 0) {
        printf("can't open input device!\n");
        if (format_opts)
            av_dict_free(&format_opts);
        return -1;
    }
    if (format_opts)
        av_dict_free(&format_opts);
    //Output Info---
    printf("---------------- File Information ---------------\n");
    av_dump_format(fmt_ctx, 0, dev_name, 0);
    printf("-------------------------------------------------\n");
    // find audio stream info
    if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
        printf("can't get audio stream info!\n");
        return -1;
    }
    int audio_stream_idx = -1;
    // find audio stream index
    for (int i = 0; i < fmt_ctx->nb_streams; i++) {
        if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            audio_stream_idx = i;
            break;
        }
    }
    if (audio_stream_idx == -1) {
        printf("can't find audio stream index!\n");
        return -1;
    }
    //write pcm data
    std::ofstream ofs("../audio/test.pcm");
    AVPacket packet;
    while (av_read_frame(fmt_ctx, &packet) >= 0) {
        if (packet.stream_index == audio_stream_idx) {
            std::cout << "packet size: " << packet.size << std::endl;
            std::cout << "packet duration: " << packet.duration << std::endl;
            ofs.write((char *) packet.data, packet.size);
            ofs.flush();
        }
        av_packet_unref(&packet);
    }
    avformat_close_input(&fmt_ctx);
    ofs.close();
    return 0;
}